# @Time : 2024-11-11 16:45
# @Author : Fioman 
# @Phone : 13149920693
"""
请求类,主要用来处理Eap的请求的类
"""
import json
import threading
from datetime import datetime

import gevent
import requests

from db_tool.db_config import TableName
from db_tool.db_handler import DbHandler
from eap_control.eap_config import EapConfig
from eap_control.eap_handler import EapHandler
from eap_control.eap_logger import EapLogger
from eap_control.resp_parse import parse_user_login_logout_report_response
from personal_tool.data_result import DataResult
from web_tool.send_to_web_handler import (update_cim_message_in_web,
                                          update_eap_data_model_in_web,
                                          update_eap_orders_in_web)
from web_tool.tool_data_model import EapDataType

ec = EapConfig()
db = DbHandler()
eapLog = EapLogger()

headers = {
    "Content-Type": "application/json",
}
timeoutDefault = 1


def request_file_path_and_parameter_request(eqp_id: str, lot_id: str, pn_id: str, panel_id: str):
    """
    向Eap发送 FilePathAndParameterRequest 请求,EQP向Eap发送请求,用来获取文件路径和参数
    :return:
    """
    methodName = "FilePathAndParameterRequest"
    data = {
        "header": ec.get_request_header(methodName),
        "body": {
            "eqp_id": eqp_id,
            "lot_id": lot_id,
            "pn_id": pn_id,
            "panel_id": panel_id
        }
    }
    url = f"{ec.request_url_base}{methodName}"
    jsonData = json.dumps(data)
    try:
        update_eap_data_model_in_web(EapDataType.dataJsonSend, data)
        resp = requests.post(url, headers=headers, data=jsonData, timeout=timeoutDefault)
    except Exception as e:
        eapLog.print_and_debug(f"Eap不在线,{methodName} 请求超时: {str(e)}")
        return ec.TimeOut
    return resp


def request_user_login_logout_report(methodName: str, work_type: str, user_no: str):
    """
    向Eap发送 UserLoginLogoutReport 请求,EQP向Eap发送请求,用来发送用户登录登出信息
    :return:
    """
    if work_type == "登入":
        # 如果是登入,就要先保证之前的用户已经登出了
        if ec.user_no:
            return DataResult(info=f"当前用户{ec.user_no}未登出,请先登出")
    else:
        # 如果是登出,先判定是否已经登入了
        # 要判断下当前的user_no是否是这个,如果不是要提示还未登录
        if user_no != ec.user_no:
            return DataResult(info=f"当前用户{user_no}未登录,请先登录")

    work_type = "1" if work_type == "登入" else "2"

    data = {
        "header": ec.get_request_header(methodName),
        "body": {
            "work_type": work_type,
            "user_no": user_no
        }
    }
    url = f"{ec.request_url_base}{methodName}"
    jsonData = json.dumps(data)
    try:
        update_eap_data_model_in_web(EapDataType.dataJsonSend, data)
        resp = requests.post(url, headers=headers, data=jsonData, timeout=timeoutDefault)
        return parse_user_login_logout_report_response(methodName, resp, user_no, work_type)
    except Exception as e:
        eapLog.print_and_debug(f"Eap不在线,{methodName} 请求超时: {str(e)}")
        return DataResult(info=f"Eap不在线,{methodName} 请求超时: {str(e)}")


def request_process_data_report(report_type: str, judge: str, process_name: str, pn_name: str, panel_id: str, proc_data_list: dict):
    """
    向Eap发送 ProcessDataReport 请求,EQP向Eap发送请求,用来发送工艺数据
    :return:
    """
    methodName = "ProcessDataReport"
    data = {
        "header": ec.get_request_header(methodName),
        "body": {
            "report_type": report_type,
            "judge": judge,
            "process_name": process_name,
            "pn_name": pn_name,
            "panel_id": panel_id,
            "proc_data_list": proc_data_list
        }
    }
    url = f"{ec.request_url_base}{methodName}"
    jsonData = json.dumps(data)
    try:
        update_eap_data_model_in_web(EapDataType.dataJsonSend, data)
        resp = requests.post(url, headers=headers, data=jsonData, timeout=timeoutDefault)
    except Exception as e:
        eapLog.print_and_debug(f"Eap不在线,{methodName} 请求超时: {str(e)}")
        return ec.TimeOut
    return resp


def request_alarm_warning_data_report(alarm_type: str, report_type: str, aw_code: str, aw_text: str):
    """
    向Eap发送 AlarmWarningDataReport 请求,EQP向Eap发送请求,用来发送报警信息
    :return:
    """
    methodName = "AlarmWarningDataReport"
    data = {
        "header": ec.get_request_header(methodName),
        "body": {
            "alarm_type": alarm_type,
            "report_type": report_type,
            "aw_code": aw_code,
            "aw_text": aw_text
        }
    }
    url = f"{ec.request_url_base}{methodName}"
    jsonData = json.dumps(data)
    try:
        update_eap_data_model_in_web(EapDataType.dataJsonSend, data)
        resp = requests.post(url, headers=headers, data=jsonData, timeout=timeoutDefault)
    except Exception as e:
        eapLog.print_and_debug(f"Eap不在线,{methodName} 请求超时: {str(e)}")
        return ec.TimeOut
    return resp


def request_equipment_status(equipment_status: str):
    """
    向Eap发送 EquipmentStatus 请求,EQP向Eap发送请求,用来获取设备状态
    :return:
    """
    methodName = "EquipmentStatus"
    data = {
        "header": ec.get_request_header(methodName),
        "body": {
            "equipment_status": equipment_status
        }
    }
    url = f"{ec.request_url_base}{methodName}"
    jsonData = json.dumps(data)
    try:
        update_eap_data_model_in_web(EapDataType.dataJsonSend, data)
        resp = requests.post(url, headers=headers, data=jsonData, timeout=timeoutDefault)
    except Exception as e:
        eapLog.print_and_debug(f"Eap不在线,{methodName} 请求超时: {str(e)}")
        return ec.TimeOut
    return resp


def request_equipment_total_count(total_count: str):
    """
    向Eap发送 EquipmentTotalCount 请求,EQP向Eap发送请求,用来获取设备总数
    :return:
    """
    total_count = str(total_count)
    methodName = "EquipmentTotalCount"
    data = {
        "header": ec.get_request_header(methodName),
        "body": {
            "total_wip_count": total_count
        }
    }
    url = f"{ec.request_url_base}{methodName}"
    jsonData = json.dumps(data)
    try:
        update_eap_data_model_in_web(EapDataType.dataJsonSend, data)
        resp = requests.post(url, headers=headers, data=jsonData, timeout=timeoutDefault)
    except Exception as e:
        eapLog.print_and_debug(f"Eap不在线,{methodName} 请求超时: {str(e)}")
        return ec.TimeOut
    return resp


def request_equipment_information(operation_mode: str, recipe_name: str, Line_Cleaning: str):
    """
    向Eap发送 EquipmentInformation 请求,EQP向Eap发送请求,用来获取设备信息
    :return:
    """
    methodName = "EquipmentInformation"
    data = {
        "header": ec.get_request_header(methodName),
        "body": {
            "operation_mode": operation_mode,
            "recipe_name": recipe_name,
            "Line_Cleaning": Line_Cleaning
        }
    }
    url = f"{ec.request_url_base}{methodName}"
    jsonData = json.dumps(data)
    try:
        update_eap_data_model_in_web(EapDataType.dataJsonSend, data)
        resp = requests.post(url, headers=headers, data=jsonData, timeout=timeoutDefault)
    except Exception as e:
        eapLog.print_and_debug(f"Eap不在线,{methodName} 请求超时: {str(e)}")
        return ec.TimeOut
    return resp


def request_equipment_current_date_time():
    """
    向Eap发送 EquipmentCurrentDateTime 请求,EQP向Eap发送请求,用来获取当前时间
    :return:
    """
    # 日期时间, 格式yyyyMMddhhmmss
    methodName = "EquipmentCurrentDateTime"
    data = {
        "header": ec.get_request_header(methodName),
        "body": {
            "date_time": datetime.now().strftime("%Y%m%d%H%M%S"),
        }
    }
    url = f"{ec.request_url_base}{methodName}"
    jsonData = json.dumps(data)
    try:
        update_eap_data_model_in_web(EapDataType.dataJsonSend, data)
        resp = requests.post(url, headers=headers, data=jsonData, timeout=timeoutDefault)
    except Exception as e:
        eapLog.print_and_debug(f"Eap不在线,{methodName} 请求超时: {str(e)}")
        return ec.TimeOut
    return resp


def request_are_you_there():
    """
    向Eap发送 DeviceHeartbeat 请求,EQP向Eap发送请求,用来询问Eap是否正常,如果收到了响应就证明是正常的
    如果没有收到响应,就证明不正常,设备上可以设定多久呼叫一次此功能,默认是60秒
    :return:
    """
    methodName = "AreYouThereRequest"
    data = {
        "header": ec.get_request_header(methodName),
        "body": {
            "user_id": ec.user_id,
            "server_ip": ec.server_ip
        }
    }
    url = f"{ec.request_url_base}{methodName}"
    jsonData = json.dumps(data)
    try:
        update_eap_data_model_in_web(EapDataType.dataJsonSend, data)
        resp = requests.post(url, headers=headers, data=jsonData, timeout=timeoutDefault)
    except Exception as e:
        eapLog.print_and_debug(f"Eap不在线,{methodName} 请求超时: {str(e)}")
        return ec.TimeOut
    return resp


def request_initial_data():
    """
    向Eap发送 InitialDataRequest 请求,EQP向Eap发送请求,用来获取初始数据
    :return:
    """
    methodName = "InitialDataRequest"
    data = {
        "header": ec.get_request_header(methodName),
        "body": EapHandler.get_initial_data_request_replay()
    }
    url = f"{ec.request_url_base}{methodName}"
    jsonData = json.dumps(data)
    try:
        update_eap_data_model_in_web(EapDataType.dataJsonSend, data)
        resp = requests.post(url, headers=headers, data=jsonData, timeout=timeoutDefault)
    except Exception as e:
        eapLog.print_and_debug(f"Eap不在线,{methodName} 请求超时: {str(e)}")
        return ec.TimeOut
    return resp


def request_trace_data_request():
    """
    "向Eap发送 TraceDataRequest 请求,EQP向Eap发送请求,用来获取追溯数据
    :return:
    """
    methodName = "TraceDataRequest"
    data = {
        "header": ec.get_request_header(methodName),
        "body": EapHandler.get_trace_data_request_replay()
    }
    url = f"{ec.request_url_base}{methodName}"
    jsonData = json.dumps(data)
    try:
        update_eap_data_model_in_web(EapDataType.dataJsonSend, data)
        resp = requests.post(url, headers=headers, data=jsonData, timeout=timeoutDefault)
    except Exception as e:
        eapLog.print_and_debug(f"Eap不在线,{methodName} 请求超时: {str(e)}")
        return ec.TimeOut
    return resp


def close_cim_message_handler(delayTime, actionType, cimMessage):
    EapHandler.cimMessageUpdateFlag = True
    for i in range(1, delayTime):
        if not EapHandler.cimMessageUpdateFlag:
            break
        gevent.sleep(1)
        update_cim_message_in_web(actionType, cimMessage, delayTime - i, True)

    eapLog.print_and_debug(f"经过了 {delayTime} 秒之后,关闭远程讯息")
    update_cim_message_in_web("", "", 0, False)


def request_file_path_and_lot_information_download(data):
    """
    向Eap发送 FilePathAndLotInformationDownload 请求,EQP向Eap发送请求,用来获取文件路径和追溯信息
    :return:
    """
    methodName = "FilePathAndLotInformationDownload"
    update_eap_data_model_in_web(EapDataType.dataJsonReceive, data)
    try:
        body = data.get("body", {})
        recipe_name = body.get("recipe_name", "")
        lot_id = body.get("lot_id", "")
        pn_id = body.get("pn_id", "")
        panel_count = body.get("panel_count", 0)  # 板子数量
        parameter_list = body.get("parameter_list", {})  # 参数列表
        parameter_items = parameter_list.get("parameter", [])

        if isinstance(parameter_items, dict):
            parameter_items = [parameter_items]
        elif not isinstance(parameter_items, list):
            parameter_items = []

        def _safe_to_float(value, default=0.0):
            try:
                if isinstance(value, (int, float)):
                    return float(value)
                if isinstance(value, str) and value.strip() != "":
                    return float(value)
            except (TypeError, ValueError):
                pass
            return float(default)

        def _safe_to_int(value, default=0):
            try:
                if isinstance(value, bool):
                    return int(value)
                if isinstance(value, int):
                    return value
                if isinstance(value, float):
                    return int(value)
                if isinstance(value, str) and value.strip() != "":
                    return int(float(value))
            except (TypeError, ValueError):
                pass
            return int(default)

        def _find_parameter_value(keywords, fallback_index):
            lowered_keywords = [kw.lower() for kw in keywords]
            for item in parameter_items:
                name = str(item.get("parameter_name", "")).lower()
                if any(kw in name for kw in lowered_keywords):
                    return _safe_to_float(item.get("parameter_value", 0))
            if 0 <= fallback_index < len(parameter_items):
                return _safe_to_float(parameter_items[fallback_index].get("parameter_value", 0))
            return 0.0

        height = _find_parameter_value(["height", "高度"], 0)
        width = _find_parameter_value(["width", "宽度"], 1)
        panel_count_value = _safe_to_int(panel_count, 0)

        # 计算任务编号
        nextTaskId = 1
        taskIdRes = db.get_data_list(TableName.eapOrders)
        if taskIdRes.state and isinstance(taskIdRes.data, list):
            existingIds = [item.get("taskId", 0) for item in taskIdRes.data if isinstance(item.get("taskId", 0), (int, float))]
            if existingIds:
                nextTaskId = int(max(existingIds)) + 1

        orderData = {
            "taskId": nextTaskId,
            "recipe_name": recipe_name,
            "lot_id": lot_id,
            "pn_id": pn_id,
            "panel_count": panel_count_value,
            "height": height,
            "width": width,
            "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        }

        insertRes = db.insert_data(TableName.eapOrders, orderData)
        if not insertRes.state:
            raise Exception(insertRes.info or "保存Eap工单数据失败")

        update_eap_orders_in_web()

        # 将这个工单保存起来并且返回
        responseData = {
            "success": True,
            "error": {
                "message": None,
                "details": None
            },
            "result": orderData
        }
        return responseData
    except Exception as e:
        eapLog.print_and_debug(f"处理FilePathAndLotInformationDownload请求失败: {str(e)}")
        responseData = {
            "success": False,
            "error": {
                "message": str(e),
                "details": None
            },
            "result": None
        }
        return responseData

def deal_cim_message_command(data):
    """
    处理CIMMessageCommand请求,EQP向Eap发送请求,用来处理CIM消息命令
    :return:
    """
    try:
        body = data.get("body", {})
        action_type = body.get("action_type")
        interval_second_time = body.get("interval_second_time", 0)
        cim_message = body.get("cim_message", "")
        update_eap_data_model_in_web(EapDataType.dataJsonReceive, data)

        if action_type == "1":  # 间隔消息,就是每隔多少秒要自动关闭
            actionTypeShow = "持续消息"
            leftTime = "never"
        else:
            actionTypeShow = "间隔消息"
            leftTime = int(interval_second_time)
            threading.Thread(target=close_cim_message_handler,
                             args=(int(interval_second_time), actionTypeShow, cim_message)).start()
        update_cim_message_in_web(actionTypeShow, cim_message, leftTime, True)

        responseData = {
            "success": True,
            "error": {
                "message": None,
                "details": None
            },
            "result": None
        }
        return responseData
    except Exception as e:
        eapLog.print_and_debug(f"处理CIMMessageCommand请求失败: {str(e)}")
        responseData = {
            "success": False,
            "error": {
                "message": str(e),
                "details": None
            },
            "result": None
        }
        return responseData
